<?php
/**
 * Copyright (c) 2006-2008, PORTALIER Julien
 * 
 * Licensed under The LGPL License
 * Redistributions of files must retain the above copyright notice.
 * 
 * @link         http://feather-cm.googlecode.com/
 * @license      http://www.opensource.org/licenses/lgpl-license.php The LGPL License
 */

abstract class GenericCommentsController extends AppController
{
	public    $restrictActions = array('create', 'edit', 'delete');
#	protected $checkActions   = array(
#		'edit'   => 'write',
#		'spam'   => 'write',
#		'troll'  => 'write',
#		'delete' => 'delete'
#	);
	protected $checkPrivate    = array('index', 'show', 'rss');
	public    $_templates      = 'comments';
	
	// internals
	
	function beforeAction()
	{
		parent::beforeAction();
		
		# private state
		if (in_array($this->action, $this->checkPrivate)
			and !$this->Acl->check("{$this->modelClass}.*", null, 'write'))
		{
			$this->model->restrictedAccess = true;
		}
	}
	
	function __get($class)
	{
		if ($class == 'model')
		{
			return $this->model = $this->{$this->modelClass};
		}
		return parent::__get($class);
	}
	
	function beforeRender()
	{
		$viewPath = (isset($this->Config->plugin['base_url']) ?
			"{$this->Config->plugin['base_url']}/" : '/').$this->viewPath;
		$this->set('viewPath', $viewPath);
	}
	
	// display
	
	function index($referer_id=null)
	{
		$page = isset($this->params['url']['page']) ? $this->params['url']['page'] : 1;
		$this->data = $this->model->getAll($referer_id, 'DESC', 24, $page);
		
		$this->pageTitle = empty($referer_id) ? _('All comments') : _('Comments');
		$this->set('robots_for_layout', 'noindex, follow');
	}
	
	function rss($referer_id=null)
	{
		$this->data = $this->model->getLatest(20, $referer_id);
		$this->layout = 'rss';
		$this->load->helper('rss');
	}
	
	function show($id)
	{
		$this->data = $this->model->read('*', $id, -1);
		
		if (HTTP::isAjax())
			$this->render('ajax_show');
		else
			$this->set('robots_for_layout', 'noindex, follow');
	}
	
	
	// admin (create, update)
	
	function create($referer_id)
	{
		$this->model->id = null;
		$this->__checkReferer($referer_id);
		
		if (empty($this->data))
		{
			$this->data = array();
			
			# remembered anonymous?
			if (!$this->Auth->identified) {
				$this->data[$this->modelClass] = $this->Auth->rememberAnonymous();
			}
			$this->data[$this->modelClass][$this->model->referer->foreignKey] = $referer_id;
		}
		else
		{
			$this->data[$this->modelClass][$this->model->referer->foreignKey] = $referer_id;
			$this->data[$this->modelClass]['member_id'] = $this->Auth->id;
			
			# anonymous posting?
			if (!$this->Auth->identified)
			{
				# stupid captcha for stupid spam bots
				if (!isset($this->data[$this->modelClass]['user_site_f'])
					or !empty($this->data[$this->modelClass]['user_site_f']))
				{
					Error::show(403);
				}
				
				# let's get paranoid!
				$this->model->paranoia = true;
				$this->data[$this->modelClass]['base_url']     = PROTOCOL.$_SERVER['HTTP_HOST'].
					(isset($this->Config->plugin, $this->Config->plugin['base_url']) ? $this->Config->plugin['base_url'] : '');
				$this->data[$this->modelClass]['permalink']    = PROTOCOL.$_SERVER['HTTP_HOST'].$this->url(null, $referer_id);
				$this->data[$this->modelClass]['article_date'] = $this->model->referer->field('created', $referer_id, -1);
        
				# troll limitation
				$troll_counter = $this->{$this->modelClass}->troll_counter();
				if ($troll_counter >= 2) {
				  Error::show(403);
				}
			}
			
			# remember anonymous member infos? 
			$this->Auth->rememberAnonymous(isset($this->data[$this->modelClass]['remember_me']) ?
				$this->data[$this->modelClass] : false);
			
			# post comment
			if ($this->model->create())
			{
				if (isset($this->data[$this->modelClass]['spam'])
					and $this->data[$this->modelClass]['spam'])
				{
					# posted but spam!
					$this->flash(_('Comment published but reported as spam.'), $this->url()."#com-{$this->model->id}", 'notice');
				}
				
				# ok!
				$this->flash(_('Comment published.'), $this->url()."#com-{$this->model->id}", 'notice');
			}
			
			if (!isset($this->params['form']['preview']) and empty($this->model->validationErrors)) {
				$this->flash(_('An error occured.'), $this->url()."#comments", 'error');
			}
		}
		$this->pageTitle = _("New comment");
	}
	
	function edit($id)
	{
		$this->__checkIfExists($id);
		$this->__checkAccessRight($id, $action='write');
		
		$this->load->component('Locker');
		$this->Locker->lock("{$this->modelClass}.$id");
		
		if (empty($this->data))
			$this->data = $this->model->read();
		elseif ($this->model->save())
		{
			$this->Locker->unlock();
#			if (HTTP::isAjax())
#			{
#				$this->layout  = 'xml';
#				$this->render('ajax_show');
#				exit;
#			}
			$this->flash(_('Comment updated.'), $this->url()."#com-$id", 'notice');
		}
		
#		if (HTTP::isAjax())
#			$this->render('ajax_edit');
#		else
#		{
			$this->data[$this->modelClass][$this->model->primaryKey] = $id;
			$this->pageTitle = _('Comment edition');
#		}
	}
	
	function spam($id)
	{
		$this->__checkIfExists($id);
		$this->__checkAccessRight($id, $action='write');
		
		$spam = !$this->model->field('spam');
		if ($this->model->saveField('spam', $spam))
#		if ($this->model->saveField('spam', 'NOT spam'))
		{
			$this->flash($spam ? _('Comment now considered as spam.') :
				_('Comment no longer considered as spam.'), $this->url()."#com-$id", 'notice');
		}
		$this->flash(_('An error occured.'), $this->url()."#com-$id", 'error');
	}
	
	function troll($id)
	{
		$this->__checkIfExists($id);
		$this->__checkAccessRight($id, $action='write');
		
		$troll = !$this->model->field('troll');
		if ($this->model->saveField('troll', $troll))
#		if ($this->model->saveField('troll', 'NOT troll'))
		{
			$this->flash($troll ? _('Comment now considered as troll.') :
				_('Comment no longer considered as troll.'), $this->url()."#com-$id", 'notice');
		}
		$this->flash(_('An error occured.'), $this->url()."#com-$id", 'error');
	}
	
	function cancel($id)
	{
		$this->load->component('Locker');
		$this->Locker->unlock("{$this->modelClass}.$id");
		
		if (!HTTP::isAjax())
			HTTP::redirect($this->url()."#com-$id");
		exit;
	}
	
	// admin (delete)
	
	function delete($id)
	{
		$this->__checkIfExists($id);
		$this->__checkAccessRight($id, 'delete');
		
		if ($this->model->delete($id))
			$this->flash(_('Comment deleted.'), HTTP::getReferer(), 'notice', 200);
		
		$this->flash(_('An error occured.'), HTTP::getReferer(), 'error', 500);
	}
	
	// internals
	
	protected function __checkIfExists($id=null)
	{
		if (!$this->model->exists($id))
			$this->flash(_('Error: no such comment.'), HTTP::getReferer(), 'error');
	}
	
	protected function __checkAccessRight($id, $action='write')
	{
		if ($this->Auth->identified)
		{
			$member_id = $this->model->field('member_id', $id);
			if (($action != 'delete' and $member_id == $this->Auth->id)
				or $this->Acl->check("{$this->modelClass}.*", null, $action))
			{
				return true;
			}
		}
		$this->Auth->permissionDenied();
	}
	
	protected function __checkReferer($referer_id)
	{
		$referer = $this->model->referer;
		if (!$referer->exists($referer_id, -1))
		{
			$this->flash(_("Error: no such reference."), '/', 'error');
		}
	}
	
	abstract function url(/*$id=null*/);
}
?>
